package services

import (
	"encoding/json"
	"fmt"
	"github.com/zhongshaofa/swan-jobs/internal/models"
	"github.com/zhongshaofa/swan-jobs/internal/repositorys"
	"github.com/zhongshaofa/swan-jobs/internal/rpc/client"
	pc "github.com/zhongshaofa/swan-jobs/internal/rpc/proto/client"
	"time"
)

var ScheduleTaskService = &schedulerTaskService{}

type schedulerTaskService struct {
}

// Delete 暂停调度任务
func (schedulerTaskService) Delete(task *models.Task, gatherList []*repositorys.ApplicationClientGather) {
	// 执行远程暂停功能
	fmt.Printf("停止远程守护进程任务：%+v\n", task)
}

// Run 运行调度任务
func (s schedulerTaskService) Run(task *models.Task, gatherList []*repositorys.ApplicationClientGather) {
	scheduleClientList := getValidClientList(task, gatherList)
	if len(scheduleClientList) == 0 {
		fmt.Println("无有效客户端可执行任务:", task.ID)
		return
	}

	var agentIds []uint
	for _, s := range scheduleClientList {
		agentIds = append(agentIds, s.ID)
	}
	scheduleAgentList, _ := json.Marshal(agentIds)

	taskScheduleRepository := repositorys.TaskScheduleInterface(repositorys.TaskScheduleRepository{})
	taskSchedule, err := taskScheduleRepository.Create(&models.TaskSchedule{
		TaskId:            int(task.ID),
		ScheduleTime:      time.Now(),
		ScheduleAgentList: string(scheduleAgentList),
	})
	if err != nil {
		fmt.Printf("taskScheduleRepository Create error:%v", err)
		return
	}

	for _, scheduleClient := range scheduleClientList {
		connectAddress := fmt.Sprintf("%s:%v", scheduleClient.Ip, scheduleClient.Port)

		request := pc.TaskRequest{
			Directory:  task.Directory,
			Command:    task.Command,
			Timeout:    int32(task.CronTimeOut),
			TaskId:     int32(task.ID),
			Mode:       int32(task.Mode),
			ScheduleId: int32(taskSchedule.ID),
			ClientId:   int32(scheduleClient.ID),
		}

		go s.remoteRun(connectAddress, task, &request)
	}
}

func (schedulerTaskService) remoteRun(connectAddress string, task *models.Task, request *pc.TaskRequest) {
	response, err := client.RunTaskByScheduler(connectAddress, request)

	fmt.Println("执行结果，内容", response, err)

	if err != nil {
		fmt.Printf("任务：%v,在客户端：%s中执行失败，原因：%s\n", task.ID, connectAddress, err)
	} else {
		fmt.Printf("任务：%v,在客户端：%s中执行成功，响应：%v\n", task.ID, connectAddress, response)
	}
}

// 获取有效客户端
func getValidClientList(task *models.Task, gatherList []*repositorys.ApplicationClientGather) []*models.Client {
	var clientList []*models.Client
	for _, gather := range gatherList {
		gatherClient := gather.Client
		if task.AppId != gather.Appid {
			continue
		}
		if gatherClient.IsHeartbeat != models.True || gatherClient.Status != models.StatusEnable {
			continue
		}
		if len(gatherClient.Ip) == 0 || gatherClient.Port == 0 {
			continue
		}
		clientList = append(clientList, gatherClient)
	}

	if len(clientList) == 0 {
		return clientList
	}

	var scheduleClientList []*models.Client
	if task.ScheduleType == models.ScheduleTypeOne {
		// 单点执行
		scheduleClientList = append(scheduleClientList, clientList[0])
	} else if task.ScheduleType == models.ScheduleTypeIdle {
		// 空闲客户端执行
		scheduleClientList = append(scheduleClientList, calculateIdleClient(clientList))
	} else {
		// 分布式执行
		scheduleClientList = clientList
	}

	return scheduleClientList
}

// 计算空闲客户端
func calculateIdleClient(clientList []*models.Client) *models.Client {
	var idleClient *models.Client
	for _, calculateClient := range clientList {
		if idleClient == nil {
			idleClient = calculateClient
			continue
		}
		if calculateClient.CalculateIdleScore() > idleClient.CalculateIdleScore() {
			idleClient = calculateClient
		}
	}
	return idleClient
}
